home *** CD-ROM | disk | FTP | other *** search
- /* $Copyright: $
- * Copyright (c) 1984, 1985, 1986 Sequent Computer Systems, Inc.
- * All rights reserved
- *
- * This software is furnished under a license and may be used
- * only in accordance with the terms of that license and with the
- * inclusion of the above copyright notice. This software may not
- * be provided or otherwise made available to, or used by, any
- * other person. No title to or ownership of the software is
- * hereby transferred.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: shbrk.c 1.3 88/03/31 $";
- #endif
-
- /*
- * shbrk.c
- * Parallel run-time basic shared memory allocator.
- *
- * Heavily based on Sequent parallel programming library shared memory
- * manager. Greatly simplified.
- */
-
- /* $Log: shbrk.c,v $
- * Revision 1.3 88/03/31 15:39:43 rbk
- * Drop all refs to "do_shared_stack" (not necessary, and value was 0).
- * Also drop all refs to _single_stack -- not needed, since signal handling
- * much simpler than microtasking code (child processes don't trap signals).
- * _init_shstk() is now a NOP since not using the microtasking library's
- * "shared stack"; drop other junk dealing with this shared stack
- * (misc #define's, variables, grow_stack()).
- * Other simplifications for simpler environment.
- *
- * Revision 1.2 88/03/24 09:52:32 rbk
- * Import MMAP macro, drop #include of parc.h. Also #unifdef -DCONCAT.
- *
- * Revision 1.1 88/03/22 15:23:28 rbk
- * Initial revision
- *
- */
-
- #ifdef sequent
-
- #include <sys/types.h>
- #include <sys/errno.h>
- #include <sys/file.h>
- #include <sys/mman.h>
- #include <sys/signal.h>
-
- #include <parallel/parallel.h>
-
- #define MMAP(fd,va,sz,pos) \
- mmap(va, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, pos)
-
- /*
- * Module local variables.
- */
-
- private int priv_stack_limit; /* size limit for priv stack */
- private static char *myshbrk; /* process local max sbrk */
- shared static char *curshbrk; /* global for all processes */
- shared static slock_t shbrk_lock = L_UNLOCKED;
-
- /*
- * _init_shbrk()
- * Initialize basic shared-memory allocator.
- *
- * Called from _ppinit().
- *
- * Since the memory manager comes into play on a SEGV signal, we have to be
- * careful that we don't get preempted at any point from within this handler,
- * since the "state" represented by the fp and sp are transient. This routine
- * must be allowed to finish without interruption.
- *
- * We also block the SIGUSR1 and SIGVTALRM signals (SIGUSR1 and SIGVTALRM
- * are used by preemption code).
- */
-
- static int segvh();
-
- static struct sigvec vec = {
- segvh,
- sigmask(SIGSEGV)|sigmask(SIGCHLD)|sigmask(SIGUSR1)|sigmask(SIGVTALRM),
- 1
- };
-
- extern void enable_interrupts();
- extern int disable_interrupts();
-
- static private int reenable_interrupts = 0;
-
- #define DISABLE_INTERRUPTS() {reenable_interrupts = disable_interrupts();}
- #define ENABLE_INTERRUPTS() {if (reenable_interrupts) enable_interrupts();}
-
- private static int segvstack[512];
- private static struct sigstack sigstruct = {(caddr_t)&segvstack[511], 0};
-
- int sigstack();
- char *getenv();
-
- _init_shbrk()
- {
- extern shared char _shend_;
-
- /*
- * Set up SIGSEGV handler; catch signal and grow shared-data
- * and shared stack if appropriate.
- */
-
- (void) sigstack(&sigstruct, (struct sigstack *)0);
- (void) sigvec(SIGSEGV, &vec, (struct sigvec *)0);
-
- /*
- * Initialize state variables.
- */
-
- curshbrk = myshbrk = &_shend_;
- return(0);
- }
-
- /*
- * shsbrk()
- * shared-memory sbrk(); create new shared space, return start address.
- */
-
- char *
- shsbrk(incr)
- int incr;
- {
- register slock_t *spin_ptr = &shbrk_lock;
- char *val;
-
- if (incr == 0)
- return(curshbrk); /* note: can race with others! */
-
- if (incr < 0) { /* can't shrink */
- errno = EINVAL;
- return((char *) -1);
- }
-
- /*
- * Lock data-file to insure one shared-brk at a time (and
- * stable value of curshbrk).
- */
-
- DISABLE_INTERRUPTS();
- S_LOCK(spin_ptr);
-
- val = curshbrk;
- if (lshbrk(val + incr) < 0)
- val = (char *) -1;
-
- S_UNLOCK(spin_ptr);
- ENABLE_INTERRUPTS();
- return(val);
- }
-
- /*
- * shbrk()
- * Add shared address space, analogous to brk().
- *
- * Just front-end to lshbrk() -- lock file and try to grow.
- */
-
- shbrk(newbrk)
- char *newbrk;
- {
- register slock_t *spin_ptr = &shbrk_lock;
- int val;
-
- DISABLE_INTERRUPTS();
- S_LOCK(spin_ptr);
-
- val = lshbrk(newbrk);
-
- S_UNLOCK(spin_ptr);
- ENABLE_INTERRUPTS();
- return(val);
- }
-
- /*
- * lshbrk()
- * "Locked" shbrk(). Internal procedure.
- *
- * Assumes caller locked shmem file, to serialize access to this code.
- * No need to check if running into bottom of UNIX private stack since
- * threads run on their own stacks.
- */
-
- static
- lshbrk(newbrk)
- register char *newbrk;
- {
- register char *cur; /* actual brk (rounded) */
- register char *new; /* requested brk (rounded) */
- extern shared char _shstart_; /* start of shared stuff */
-
- /*
- * Not allowed to shrink self (yet).
- */
-
- if (newbrk < myshbrk) {
- errno = EINVAL;
- return(-1);
- }
-
- /*
- * Growing: if no actual increase (rounding/etc), just adjust
- * (self) myshbrk.
- */
-
- cur = PGRND(myshbrk);
- if (cur >= newbrk) {
- myshbrk = newbrk;
- if (newbrk > curshbrk)
- curshbrk = myshbrk;
- return(0);
- }
- new = PGRND(newbrk);
-
- /*
- * Need to mmap() more of file.
- */
-
- if (MMAP(_shm_fd, cur, new - cur, cur - &_shstart_) < 0) {
- errno = ENOMEM;
- return(-1);
- }
-
- myshbrk = newbrk; /* maybe not aligned */
- if (newbrk > curshbrk)
- curshbrk = newbrk; /* grew the global memory */
-
- return(0); /* success! */
- }
-
- /*
- * _init_shstk()
- * Initialize microtasking shared-stack.
- *
- * Called from _ppinit().
- */
-
- int *
- _init_shstk(ctxt_bottom, ctxt_top)
- int *ctxt_bottom;
- int *ctxt_top;
- {
- /*
- * NOP -- never called since not using "microtask shared stack".
- */
- return(0);
- }
-
- /*
- * segvh()
- * SIGSEGV handler.
- *
- * If process isn't up to max shared-data, get there and re-try the
- * instruction. Else turn off handler and retry (==> dump core).
- */
-
- /*ARGSUSED*/
- static
- segvh(sig, code, scp)
- int sig, code;
- struct sigcontext *scp;
- {
- register slock_t *spin_ptr = &shbrk_lock;
- register int *fa = (int *)code;
-
- /*
- * A signal code of -1 indicates the signal originated from a
- * kill() system call, rather than a real program fault.
- */
-
- if (fa == (int *)-1) {
- (void) signal(SIGSEGV, SIG_DFL);
- (void) kill(getpid(), SIGSEGV);
- return;
- }
-
- /*
- * If process doesn't have all of shared heap mapped, map it and retry.
- * Otherwise turn off SIGSEGV handling.
- *
- * Lock data-file during this to stabilize curshbrk and
- * insure only one lshbrk() at a time.
- *
- * Return retries instruction, will die for real if turn off
- * signal handling here.
- */
-
- DISABLE_INTERRUPTS();
- S_LOCK(spin_ptr);
-
- if (myshbrk >= curshbrk || lshbrk(curshbrk) < 0)
- (void) signal(SIGSEGV, SIG_DFL);
-
- S_UNLOCK(spin_ptr);
- ENABLE_INTERRUPTS();
- }
-
- #endif sequent
-